﻿/***************************************************************************
//* Foxit Software Inc.
//* Copyright(C) 2005-2012, all rights reserved.
//*
//* The following code is copyrighted and contains proprietary information
//* and trade secrets of Foxit Software Inc.                                                      *
***************************************************************************/

/**
* 搜索Annot插件类
*/



define(function (require, exports, module) {

    var CFindTool_DocViewEventHandler = require('./FindToolDocViewEventHandler');



    //存储搜索结果;
    FXREADER.CSearchResult = function () {
        this.m_nStartCharIndex = -1;
        this.m_szRelateText = "";
        this.m_Rects = [];          //存储搜索结构的矩形区域;
    }
    //存储页面搜索结果;
    FXREADER.CPageSearchResult = function () {
        this.m_bSearched = false;
        this.m_bHasResult = false;
        this.m_nPageIndex = -1;
        this.m_nTotalCharCnt = -1;
        this.m_nCurResultIndex = -1;
        this.m_nResultList = [];
        this.ClearResult = function () {
            this.m_bSearched = false;
            this.m_bHasResult = false;
            this.m_nPageIndex = -1;
            this.m_nTotalCharCnt = -1;
            this.m_nCurResultIndex = -1;
            this.m_nResultList = [];
        }
        this.IsLastResult = function (nCurSelIndex) {
            return nCurSelIndex == (this.m_nResultList.length - 1);
        }
        this.IsFirstResult = function (nCurSelIndex) {
            return nCurSelIndex == 0;
        }
        this.GetNextCharIndex = function (nCurSelIndex) {
            return this.m_nResultList[nCurSelIndex + 1].m_nStartCharIndex;
        }
        this.GetPrevCharIndex = function (nCurSelIndex) {
            return this.m_nResultList[nCurSelIndex - 1].m_nStartCharIndex;
        }
        this.GetLastCharIndex = function () {
            iCnt = this.m_nResultList.length - 1;
            if (iCnt < 0)
                iCnt = 0;
            if (this.m_nResultList[iCnt] == null)
                return 0;
            return this.m_nResultList[iCnt].m_nStartCharIndex;
        }
    }
    /**
    * 搜索参数;
    * @param [iPageIndex] 页面索引;
    * @param [iCharIndex] 相对于页面的字符索引;
    */
    FXREADER.CSearchParam = function (iPageIndex, iCharIndex) {
        this._iPageIndex = iPageIndex;
        this._iCharIndex = iCharIndex;
    }


    FXREADER.SearchDataJsonFormat = {
        //         bFind: "bf",
        //         Pages: "pgs",
        //         PageNum: "pn",
        //         CharCount: "cc",
        //         CurResultIndex: "cri",
        //         ResultCount: "rec",
        //         Results: "res",
        //         StartCharIndex: "sci",
        //         ResultRects: "rercs",
        //         RelateText: "rltxt"
        bFind: "find",
        Pages: "pages",
        PageNum: "pagenum",
        CharCount: "charcnt",
        CurResultIndex: "curindex",
        ResultCount: "resultcnt",
        Results: "results",
        StartCharIndex: "startchar_index",
        ResultRects: "rects",
        RelateText: "text"
    }
    var SearchDataJsonFormat = FXREADER.SearchDataJsonFormat;

    FXREADER.CFindToolPlugin = function (pReaderApp) {
        //private members
        var _pReaderApp = pReaderApp,
             _SearchText = '',                         //上一次搜索的字符串;
             _PageFindResults = [],                 //临时存储页面搜索结果;
             _nCurPageIndex = -1,                //上一次搜索结果所处页面;
             _CurCharIndex = -1,                  //上一次搜索结果的字符索引;
             _CurSelIndex = -1,                     //上一次搜索结果相对于页面搜索结果的索引（一个页面包含多个搜索结果 CSearchResult）;
             _StartPageIndex = -1,                //第一次搜索的页面索引;
			 _FirstSearchedCharIndex = -1,             //第一次搜索的字符索引
             _bCaseSensitive = 0,                  //搜索参数：是否大小写匹配;
             _bMarchWholeWord = 0,           //搜索参数：是否匹配整个单词;
             _bInSearch = 0,                         //是否正在查找中;
             _PageHighlightCreatedList = {},  // 存储已经创建highlight div的页面索引,格式为 :   页面索引：true/fase;
             _SearchDivID =   _pReaderApp.GetMainView().GetDocView().GetDocViewContainerID() + "_SearchingDiv",  //搜索层的id;
             _SearchLoadingTextId = _SearchDivID + "_LoadingText",  //搜索层文本ID
             _SearchingText = "Searching",                                          //搜索层文本;
             _HighlightRects = null,  //当前需要高亮的矩形区域;
             _Language = _pReaderApp.GetLanguage(),
			 _bReturnToStartPage = true,
		     _bReturnToFirstSearchedPos = false,
			 _bFirstSearchDown = null,
			 _bUnsearchFromServer = false,
             _self = this;

        var _LoadingIntervalID = null;  //搜索文本变化的SetInterval ID;

        //private methods
        //判断是否是个新搜索;
        function _IsNewSearch(szNewSearchText) {
            return !(_SearchText == szNewSearchText);
        }
        //清除存储在本地的搜索结果;
        function _ClearResult() {
            var iPageCnt = _pReaderApp.GetMainView().GetDocView().GetPageCount();
            for (var i = 0; i < iPageCnt; i++) {
                _PageFindResults[i].ClearResult();
            }
        }
        //清空所有搜索相关数据;
        function _Reset() {
            _SearchText = '';
            _self.ResetHighLightText(true);
            _nCurPageIndex = -1;
            _CurCharIndex = -1;
            _StartPageIndex = -1;
			_FirstSearchedCharIndex = -1;
            _ClearResult();
        }


        function _GetHighlightDivID(pPageView) {
            return pPageView.GetPageContainerID() + "_HighLights";
        }

        function _FindedCallBack(find_result, iPageNum, txt2Search, curSelIndex) {
			if(_StartPageIndex !=-1 && _StartPageIndex==iPageNum && find_result.m_nStartCharIndex==_FirstSearchedCharIndex)
			{
				/* var pDocView = _pReaderApp.GetMainView().GetDocView();
				 _self.ResetHighLightText();
                            //回到第一次搜索的页面;
                //pDocView.GotoPage(_StartPageIndex);
                _nCurPageIndex = -1;
                _CurCharIndex = -1;
                 _StartPageIndex = -1;
				_FirstSearchedCharIndex = -1;
               // FXREADER.Alert("", _Language.Search.NoMoreMatch);
				return false;*/
				_bReturnToFirstSearchedPos = true;
			}

            _self.ResetHighLightText(true);
			var bSameResult = (_CurCharIndex==find_result.m_nStartCharIndex && _CurSelIndex==curSelIndex && _nCurPageIndex==iPageNum);
            _nCurPageIndex = iPageNum;
            _self.SetHightlightRects(find_result.m_Rects);
			if(!bSameResult)
				_self.HilightSearchedText(_nCurPageIndex, _HighlightRects);
			else
				setTimeout(function(){_self.HilightSearchedText(_nCurPageIndex, _HighlightRects);},50);
            _CurCharIndex = find_result.m_nStartCharIndex;
            _SearchText = txt2Search;
            _CurSelIndex = curSelIndex;
            if (_StartPageIndex == -1) {
                _StartPageIndex = _nCurPageIndex;
				_FirstSearchedCharIndex = _CurCharIndex;
            }
			return true;
        }

        function _SearchInAPageResult(i, page_result, start_char_index, iCurPageIndex, txt2Search, bDown) {
            var nOldSearchPageIndex = _nCurPageIndex;
            if (bDown == 1) {
                for (var j = 0; j < page_result.m_nResultList.length; j++) {
                    var result = page_result.m_nResultList[j];
                    if (i == iCurPageIndex) {
                        if (result.m_nStartCharIndex >= start_char_index) {
                            return _FindedCallBack(result, i, txt2Search, j);
                        }
                    }
                    else {
                        return _FindedCallBack(result, i, txt2Search, j);
                    }
                }
            }
            else {
                for (var j = page_result.m_nResultList.length - 1; j >= 0; j--) {
                    var result = page_result.m_nResultList[j];
                    if (i == iCurPageIndex) {
                        if (result.m_nStartCharIndex <= start_char_index) {
                            return _FindedCallBack(result, i, txt2Search, j);
                        }
                    }
                    else {
                        return _FindedCallBack(result, i, txt2Search, j);
                    }
                }
            }

            return false;
        }


        function _SearchInRange(iStartIndex, iEndIndex, start_char_index, iCurPageIndex, txt2Search, bDown) {
            var bFind = false;
            if (bDown == 1) {
                for (var i = iStartIndex; i < _PageFindResults.length && !bFind && i <= iEndIndex; i++) {
                    var page_result = _PageFindResults[i];
                    if (page_result == null || page_result.m_bSearched == false)
                    {
						_bUnsearchFromServer = true;
						break;
					}
                    if (!page_result.m_bHasResult)
                        continue;
                    bFind = _SearchInAPageResult(i, page_result, start_char_index, iCurPageIndex, txt2Search, 1);
                    if (bFind)
                        return true;
                }
            }
            else {
                for (var i = iEndIndex; i >= 0 && !bFind && i >= iStartIndex; i--) {
                    var page_result = _PageFindResults[i];
                    if (page_result == null || page_result.m_bSearched == false)
                    {
						_bUnsearchFromServer = true;
						break;
					}
                    if (!page_result.m_bHasResult)
                        continue;
                    bFind = _SearchInAPageResult(i, page_result, start_char_index, iCurPageIndex, txt2Search, 0);
                    if (bFind)
                        return true;
                }
            }
            return false;
        }

        //创建一个新的服务端搜索;
        function _CreateANewServerSearch(txt2Search, start_char_index, pageindex, bDown) {
            var pDocView = _pReaderApp.GetMainView().GetDocView();
            var iPageCnt = pDocView.GetPageCount();
            var post_data = { fileid: pReaderApp.GetFileID(), key: encodeURIComponent(txt2Search), page: pageindex, charIndex: start_char_index, indoc: 0, pagecnt: iPageCnt,
                firstPage: _StartPageIndex, bDown: bDown, bCase: _bCaseSensitive, bWord: _bMarchWholeWord
            };
            _bInSearch = 1;

            $.ajax({
                cache: false,
                type: "POST",
                url: FXREADER.Config.Url.SearchText,
                data: post_data,
                error: function (c) {
                    _bInSearch = 0;
                    //取消搜索状态动画;
                    clearInterval(_LoadingIntervalID);
                    _self.ShowSearchingDiv(0);
                },
                success: function (responseText) {
                    clearInterval(_LoadingIntervalID);
                    _self.ShowSearchingDiv(0);
                    _bInSearch = 0;
                    if (responseText == "") {
                        if (_StartPageIndex == -1) {
                            _CurSelIndex = -1;
                            _CurCharIndex = -1;
                            _StartPageIndex = -1;
							_FirstSearchedCharIndex = -1;
                            FXREADER.Alert("", _Language.Search.NoFound);
                        }
                        else {
                            _self.ResetHighLightText(false);
							setTimeout(function(){_self.OnDocViewZoom(1.0);},50);
                            //回到第一次搜索的页面;
                           // pDocView.GotoPage(_StartPageIndex);
                            /*_nCurPageIndex = -1;
                            _CurCharIndex = -1;
                            _StartPageIndex = -1;
							_FirstSearchedCharIndex = -1;
							_CreateANewServerSearch(txt2Search, start_char_index, pageindex, bDown);*/
                           /* FXREADER.Alert("", _Language.Search.NoMoreMatch);*/
						   
                        }
                    }
                    else {
                        result = JSON.parse(responseText);
                        var bFind = result[SearchDataJsonFormat.bFind];
                        if (!bFind) {
                            for (var i = 0; i < iPageCnt; i++) {
                                var page_result_i = _PageFindResults[i];
                                page_result_i.m_bSearched = true;
                                page_result_i.m_bHasResult = false;
                            }
                            FXREADER.Alert("", _Language.Search.SearchFail);
                        }
                        else {
                            json_page_result = result[SearchDataJsonFormat.Pages][0];
                            var iPageNum = json_page_result[SearchDataJsonFormat.PageNum];
                            var page_result = _PageFindResults[iPageNum];
                            page_result.ClearResult();
                            page_result.m_nPageIndex = iPageNum;
                            page_result.m_bSearched = true;
                            page_result.m_bHasResult = true;
                            page_result.m_nTotalCharCnt = json_page_result[SearchDataJsonFormat.CharCount];
                            page_result.m_nCurResultIndex = json_page_result[SearchDataJsonFormat.CurResultIndex];
                            rect_results = json_page_result[SearchDataJsonFormat.Results];
                            for (var j = 0; j < rect_results.length; j++) {
                                var json_result = rect_results[j];
                                page_result.m_nResultList[j] = new FXREADER.CSearchResult();
                                var aresult = page_result.m_nResultList[j];
                                aresult.m_szRelateText = json_result[SearchDataJsonFormat.RelateText];
                                aresult.m_nStartCharIndex = json_result[SearchDataJsonFormat.StartCharIndex];
                                var rects = json_result.rects;
                                for (var k = 0; k < rects.length; k++) {
                                    var json_rect = rects[k];
                                    aresult.m_Rects[k] = new FXREADER.CPDF_Rect(json_rect[0], json_rect[1], json_rect[0] + json_rect[2], json_rect[3] + json_rect[1]);
                                }

                            }
                            if (bDown == 1) { //向下搜索
                                if (iPageNum < pageindex) { //返回头部搜索
                                    for (var i = pageindex; i < _PageFindResults.length; i++) {
                                        var page_result_i = _PageFindResults[i];
                                        page_result_i.m_bSearched = true;
                                        page_result_i.m_bHasResult = false;
                                    }
                                    for (var i = 0; i < iPageNum; i++) {
                                        var page_result_i = _PageFindResults[i];
                                        page_result_i.m_bSearched = true;
                                        page_result_i.m_bHasResult = false;
                                    }
                                }
                                else {
                                    for (var i = pageindex; i < iPageNum; i++) {
                                        var page_result_i = _PageFindResults[i];
                                        page_result_i.m_bSearched = true;
                                        page_result_i.m_bHasResult = false;
                                    }
                                }
                            }
                            else {
                                if (iPageNum <= pageindex) {
                                    for (var i = iPageNum + 1; i < pageindex; i++) {
                                        var page_result_i = _PageFindResults[i];
                                        page_result_i.m_bSearched = true;
                                        page_result_i.m_bHasResult = false;
                                    }
                                }
                                else {
                                    for (var i = 0; i < pageindex; i++) {
                                        var page_result_i = _PageFindResults[i];
                                        page_result_i.m_bSearched = true;
                                        page_result_i.m_bHasResult = false;
                                    }
                                    for (var i = iPageNum + 1; i < _PageFindResults.length; i++) {
                                        var page_result_i = _PageFindResults[i];
                                        page_result_i.m_bSearched = true;
                                        page_result_i.m_bHasResult = false;
                                    }
                                }
                            }
                            _self.ResetHighLightText(true);
							var bSameResult = (_CurCharIndex==page_result.m_nResultList[page_result.m_nCurResultIndex].m_nStartCharIndex
								&& _CurSelIndex==json_page_result[SearchDataJsonFormat.CurResultIndex] && _nCurPageIndex==iPageNum);
                            _nCurPageIndex = iPageNum;
                            _self.SetHightlightRects(page_result.m_nResultList[page_result.m_nCurResultIndex].m_Rects);
							if(!bSameResult)
								 _self.HilightSearchedText(_nCurPageIndex, _HighlightRects);
							else
								 setTimeout(function(){_self.HilightSearchedText(_nCurPageIndex, _HighlightRects);},50);
                            _CurCharIndex = page_result.m_nResultList[page_result.m_nCurResultIndex].m_nStartCharIndex;
                            _SearchText = txt2Search;
                            _CurSelIndex = json_page_result[SearchDataJsonFormat.CurResultIndex];
                            if (_StartPageIndex == -1) {
                                _StartPageIndex = iPageNum;
								_FirstSearchedCharIndex = _CurCharIndex;
                            }
                        }
                    }
                }
            });

        }

        //public methods
        //根据页面和需要高亮的区域，获取滚动条需要移动的位置; 返回{x:-1,y:-1}代表可见或获取失败
        this.GetHighlightOffset2Scroll = function (pPageView, highlightRects) {
            if (highlightRects.length <= 0)
                return { x: -1, y: -1 };
            var first_rect = highlightRects[0];
            FXREADER.RectUtils.Normalize(first_rect);
            var union_rect = new FXREADER.CPDF_Rect(first_rect.left, first_rect.top, first_rect.right, first_rect.bottom);
            for (var i = 1; i < highlightRects.length; i++) {
                var tmp_rect = highlightRects[i];
                FXREADER.RectUtils.Normalize(tmp_rect);
                FXREADER.RectUtils.Union(union_rect,tmp_rect);
            }
            var pDocView = _pReaderApp.GetMainView().GetDocView();
            var jqDocView = $("#" + pDocView.GetDocViewContainerID());
            //var docViewScrollTop = jqDocView.scrollTop();
            var pagesContainerHeight = jqDocView.height(), pagesContainerWidth = jqDocView.width(),
                    pagesContainerOffset = jqDocView.offset();
            var jqPageView = $("#" + pPageView.GetPageContainerID());
            if (pPageView.GetDocView().GetViewMode() == FXREADER.PDFView.RD_BRMODE_CONTINUOUS_FACING) { //双页；
                //暂时不处理；
            }
            else if (pPageView.GetDocView().GetViewMode() == FXREADER.PDFView.RD_BRMODE_CONTINUOUS) { //单页；
                var pageOffset = jqPageView.offset();
                var docrect = pPageView.PDF2Doc(union_rect, true);
                var center_y = pagesContainerHeight / 2;
                var center_x = pagesContainerWidth / 2;
                var bVisable = ((pageOffset.top + docrect.top >= pagesContainerOffset.top) && (pageOffset.top + docrect.top <= pagesContainerOffset.top + pagesContainerHeight))
                                                || ((pageOffset.top + docrect.top <= pagesContainerOffset.top) && (pageOffset.top + docrect.top + FXREADER.RectUtils.Height(docrect) >= pagesContainerOffset.top));
                bVisable &= ((pageOffset.left + docrect.left >= pagesContainerOffset.left) && (pageOffset.left + docrect.left <= pagesContainerOffset.left + pagesContainerWidth))
                                                || ((pageOffset.left + docrect.left <= pagesContainerOffset.left) && (pageOffset.left + docrect.left + FXREADER.RectUtils.Width(docrect) >= pagesContainerOffset.left));
                if (bVisable == 1)
                    return { x: -1, y: -1 };
                var rect_top_pos_y = FXREADER.RectUtils.Height(docrect) / 2;
                page_top_pos_y = rect_top_pos_y + docrect.top;
                page_top_pos_y = center_y - page_top_pos_y;
                page_top_pos_y = -page_top_pos_y;
                var rect_left_pos_x = FXREADER.RectUtils.Width(docrect) / 2;
                var page_left_pos_x = rect_left_pos_x + docrect.left;
                page_left_pos_x = center_x - page_left_pos_x;
                page_left_pos_x = -page_left_pos_x;

                return { x: page_left_pos_x, y: page_top_pos_y };
            }
        }

        this.HilightSearchedText = function (iPageIndex, highlightRects) {
            var pDocView = _pReaderApp.GetMainView().GetDocView();
            if (iPageIndex < 0 || iPageIndex >= pDocView.GetPageCount())
                return false;
            var pPageView = pDocView.GetPageView(iPageIndex);
            if (!pPageView.IsContentCreated())
                pDocView.GotoPage(iPageIndex, 0, 0);
            var offset = _self.GetHighlightOffset2Scroll(pPageView, highlightRects);
            if (offset.x != -1 && offset.y != -1) {
                pDocView.GotoPage(iPageIndex, offset.x, offset.y);
            }
            _self.HighLightRects(pPageView, highlightRects);
        }

        this.HighLightRects = function (pPageView, highlightRects) {
            if (pPageView == null || !pPageView.IsContentCreated() || highlightRects == null)
                return false;
            var highLightDivID = _GetHighlightDivID(pPageView);
            if (_PageHighlightCreatedList[pPageView.GetPageIndex()] == null) {
                var highLightDivHtml = "<div id='" + highLightDivID + "' style='z-index:7;'></div>";
                var jqPageView = $("#" + pPageView.GetPageContainerID());
                jqPageView.append(highLightDivHtml);
                _PageHighlightCreatedList[pPageView.GetPageIndex()] = true;
            }
            var jqHighlightDiv = $("#" + highLightDivID);
            jqHighlightDiv.empty(); //清空原有的div内容;

            var highLightDivContent = "";
            for (var i = 0; i < highlightRects.length; i++) {
                var rect = highlightRects[i];
                FXREADER.RectUtils.Normalize(rect);
                rect = pPageView.PDF2Doc(rect, true);
                highLightDivContent += "<div id='" + "highlight_" + pPageView.GetPageIndex() + "_" + i + "'class='fwr_text_highlight' style='left:" +
                             rect.left + "px;top:" + rect.top + "px;width:" + FXREADER.RectUtils.Width(rect) + "px;height:" + FXREADER.RectUtils.Height(rect) + "px' ></div>";
            }
            jqHighlightDiv.append(highLightDivContent);
        }

        this.SetHightlightRects = function (rects) {
            _HighlightRects = [];
            _HighlightRects = rects.concat();
        }

        this.ResetHighLightText = function (bClearRects) {
			if(bClearRects == true)
            _HighlightRects = [];
            var pPageView = _pReaderApp.GetMainView().GetDocView().GetPageView(_nCurPageIndex);
            if (pPageView != null) {
                var highLightDivID = _GetHighlightDivID(pPageView);
                var jqHighlightDiv = $("#" + highLightDivID);
                if (jqHighlightDiv != null) {
                    jqHighlightDiv.empty();
                }
            }
        }

        this.ShowSearchingDiv = function (bShow) {
            var jqobj = $("#" + _SearchDivID);
            bShow ? jqobj.show() : jqobj.hide();
        }

        this.UpdateSearchLoadingText = function (iStep) {
            var text = _SearchingText;
            for (var i = 0; i < iStep; i++)
                text = text + ".";
            $("#" + _SearchLoadingTextId).text(text);
        }


        this.SetSearchParam = function (bCaseSensitive, bMarchWholeWord) {
            if (_bInSearch == 1)
                return;
            if (_bCaseSensitive != bCaseSensitive || _bMarchWholeWord != bMarchWholeWord)
                _Reset();
            _bCaseSensitive = bCaseSensitive;
            _bMarchWholeWord = bMarchWholeWord;
        }

        //获取下一个搜索的位置;
        this.GetNextSearchIndex = function () {
			_bReturnToStartPage = false;
            if (_CurCharIndex == -1 || _nCurPageIndex == -1 || _SearchText == '' || _CurSelIndex == -1)
                return "New";
            page_result = _PageFindResults[_nCurPageIndex];
            if (page_result.IsLastResult(_CurSelIndex)) {
                var next_page = _nCurPageIndex >= _PageFindResults.length - 1 ? 0 : _nCurPageIndex + 1;
				var nextCharIndex = 0;
				if(_StartPageIndex!=-1 && next_page==_StartPageIndex)
				{
					_bReturnToStartPage = true;
				}
                return new FXREADER.CSearchParam(next_page, nextCharIndex);
            }
            else {
				if(_StartPageIndex!=-1 && _nCurPageIndex==_StartPageIndex)
				{
					_bReturnToStartPage = true;
				}
                return new FXREADER.CSearchParam(_nCurPageIndex, page_result.GetNextCharIndex(_CurSelIndex));
            }
        }
        //获取上一个搜索的位置;
        this.GetPrevSearchIndex = function () {
            if (_CurCharIndex == -1 || _nCurPageIndex == -1 || _SearchText == '' || _CurSelIndex == -1)
                return "New";
            var iPageCnt = _pReaderApp.GetMainView().GetDocView().GetPageCount();
            page_result = _PageFindResults[_nCurPageIndex];
            if (page_result.IsFirstResult(_CurSelIndex)) {
				var next_page = 0
                if (_nCurPageIndex >= 1)
					next_page = _nCurPageIndex - 1;
				else
					next_page = iPageCnt - 1;
				if(_StartPageIndex!=-1 && next_page==_StartPageIndex)
				{
					_bReturnToStartPage = true;
				}
                return new FXREADER.CSearchParam(next_page, _PageFindResults[next_page].GetLastCharIndex());
            }
            else {
				if(_StartPageIndex!=-1 && _nCurPageIndex==_StartPageIndex)
				{
					_bReturnToStartPage = true;
				}
                return new FXREADER.CSearchParam(_nCurPageIndex, page_result.GetPrevCharIndex(_CurSelIndex));
            }
        }

        /**
        * 搜索文本;
        * @param [txt2Search] 需要搜索的文本;
        * @param [nStartCharIndex] 相对于页面的字符索引;
        * @param [iPageIndex] 起始页面索引;
        * @param [bDown] 是否向下搜索;
        */
        this.SearchText = function (txt2Search, nStartCharIndex, iPageIndex, bDown) {
            if (_bInSearch == 1)  //正在搜索中；
                return;
            var bFind = false;
            var find_result = null;

            _self.ShowSearchingDiv(1);  //显示搜索层
            var nCnt = 0;
            //_eViewerManager.UpdateSearchBtnStateV2(1);
            _LoadingIntervalID = setInterval(function () {  //动画更新搜索文本
                if (nCnt == 4)
                    nCnt = 0;
                _self.UpdateSearchLoadingText(nCnt);
                nCnt++;
            }, 300);
			_bUnsearchFromServer = false;
            if (_IsNewSearch(txt2Search)) {  //是否新搜索;
                _Reset();
                _CreateANewServerSearch(txt2Search, 0, iPageIndex, bDown);
            }
            else { //已经搜索到过
                var i = iPageIndex;
                if (_StartPageIndex != -1) {

                    if (bDown == 1) {
                            bFind = _SearchInRange(iPageIndex, _PageFindResults.length - 1, nStartCharIndex, iPageIndex, txt2Search, 1);
                            if (!bFind && !_bUnsearchFromServer)
                                bFind = _SearchInRange(0, iPageIndex-1, nStartCharIndex, iPageIndex, txt2Search, 1);
                    }
                    else {
                            bFind = _SearchInRange(0, iPageIndex, nStartCharIndex, iPageIndex, txt2Search, 0);
                            if (!bFind && !_bUnsearchFromServer)
                                bFind = _SearchInRange(iPageIndex+1 , _PageFindResults.length - 1, nStartCharIndex, iPageIndex, txt2Search, 0);
                        }
                    }
                if (bFind) {
					if(_bReturnToFirstSearchedPos)
					{
						_bReturnToFirstSearchedPos = false;
						//var next_page = _nCurPageIndex >= _PageFindResults.length - 1 ? 0 : _nCurPageIndex + 1;
						// _CreateANewServerSearch(txt2Search, 0, next_page, bDown);
						//alert('return pt');
						clearInterval(_LoadingIntervalID);
						_self.ShowSearchingDiv(0);
						
					}
					else
					{
						clearInterval(_LoadingIntervalID);
						_self.ShowSearchingDiv(0);
					}
                }
                else {
                    _CreateANewServerSearch(txt2Search, 0, i, bDown);
                }
            }

            return bFind;
        }

        this.SearchTextDown = function (txt2Search) {
			_bFirstSearchDown = true;
            var nextSearch = _self.GetNextSearchIndex();
            var iCurPageIndex = _pReaderApp.GetMainView().GetDocView().GetCurPageIndex();
            if (nextSearch == "End") {
            }
            else if (nextSearch == "New") {
                if (_self.SearchText(txt2Search, 0, iCurPageIndex, 1)) {
                }
            }
            else {
                if (_self.SearchText(txt2Search, nextSearch._iCharIndex, nextSearch._iPageIndex, 1)) {
                }
            }
        }

        this.SearchTextUp = function (txt2Search) {
			_bFirstSearchDown = false;
            var nextSearch = _self.GetPrevSearchIndex();
            var iCurPageIndex = _pReaderApp.GetMainView().GetDocView().GetCurPageIndex();
            if (nextSearch == "End") {
            }
            else if (nextSearch == "New") {
                if (_self.SearchText(txt2Search, 0, iCurPageIndex, 0)) {
                }
            }
            else {
                if (_self.SearchText(txt2Search, nextSearch._iCharIndex, nextSearch._iPageIndex, 0)) {
                }
            }
        }


        //public methods
        //获取Plugin名称;
        this.GetPluginName = function () {
            return "Find Tool Plugin";
        }
        //插件被注册的时候调用;
        this.PIOnRegister = function () {
            
        }
        //模块初始化;
        this.PIInit = function () {
            _SearchDivID = _pReaderApp.GetMainView().GetDocView().GetDocViewContainerID() + "_SearchingDiv";  //搜索层的id;
            _self.CreateCmdAndCmdUI();
            var iPageCnt = _pReaderApp.GetMainView().GetDocView().GetPageCount();
            for (var i = 0; i < iPageCnt; i++) {
                _PageFindResults[i] = new FXREADER.CPageSearchResult();
            }
            $("#" + _pReaderApp.GetMainView().GetDocView().GetDocViewContainerID()).append("<div id='" + _SearchDivID + "' class='fwr_searching_div' ><img src='images/searching_loading.png' class='fwr_searching_div_content' style='width:16px;height:16px;margin-left:16px;'></img><label class='fxsearching_divcontent' style='margin-left:2px;' id='" + _SearchLoadingTextId + "'>Searching...</label></div>");
            _self.ShowSearchingDiv(0);
            var pFindToolDocViewEventHandler = new CFindTool_DocViewEventHandler(_self);
            _pReaderApp.RegisterDocViewEventHandler(pFindToolDocViewEventHandler);

            _pReaderApp.StepProgress();
        }

        //模块卸载;
        this.PIUnload = function () {
        }

        this.GetReaderApp = function () {
            return _pReaderApp;
        }


        function _SearchTextCall(bSearchDown) {
            var jqTextSearch = $("#textsearch");
            if (jqTextSearch != null) {
                var txtSearch = jqTextSearch.val();
                txtSearch = txtSearch.replace(/(^\s*)|(\s*$)/g, "");
                if (txtSearch == '')
                    return;
                if (bSearchDown == 0)
                    _self.SearchTextUp(txtSearch);
                else
                    _self.SearchTextDown(txtSearch);
            }
        }

        this.CreateCmdAndCmdUI = function () {
            _pReaderApp.AddCommandUI({
                UIName: "SearchText",
                CommandName: null,
                State: false,
                CreateHtmlContentFunc: function () {
                    return "<div class='fwr_toolbar_search_icon_div'><img src='images/search.png'/></div><input id='textsearch'' class='fwr_text_input fwr_toolbar_search_input' type='text' value=''  disabled='disabled'/>"
                },
                OnCommandStateChange: function (data) {
                },
                Init: function () {
                    var jqTextSearch = $("#textsearch");
                    jqTextSearch.removeAttr("disabled");
                    $(function () {
                        function _UpdataBtnState() {
                            var txtSearch = jqTextSearch.val();
                            txtSearch = txtSearch.replace(/(^\s*)|(\s*$)/g, "");
                            var bEnable = !(txtSearch == "");
                            var pSearchPrevCommand = _pReaderApp.GetCommand("SearchPrev");
                            pSearchPrevCommand && pSearchPrevCommand.SetState(bEnable);
                            var pSearchNextCommand = _pReaderApp.GetCommand("SearchNext");
                            pSearchNextCommand && pSearchNextCommand.SetState(bEnable);
                        }
                        //IE
                        if (FXREADER.Environment.ie) {
                            jqTextSearch.get(0).attachEvent("onpropertychange", function (o) {
                                _UpdataBtnState();
                            });
                            //非IE
                        } else {
                            jqTextSearch.get(0).addEventListener("input", function (o) {
                                _UpdataBtnState();
                            }, false);
                        }

                        jqTextSearch.bind("click", function () {
                            jqTextSearch.focus();
                            return true;
                        });
                        jqTextSearch.bind("keypress", function (d) {
                            d.keyCode == "13" && _SearchTextCall(1);
                            return true;
                        });

                        jQuery.hotkeys.add('f3', function () {
                            _SearchTextCall(1);
                            return false;
                        });

                        jQuery.hotkeys.add('Shift+f3', function () {
                            _SearchTextCall(0);
                            return false;
                        });

                    });
                }
            });
            _pReaderApp.AddCommandUI({
                UIName: "SearchPrev",
                CommandName: 'SearchPrev',
                State: false,
                CreateHtmlContentFunc: function () {
                    return "<a id='btnPrevSearch' class='fwr_toolbar_btn fwr_toolbar_search_btn fwr_toolbar_search_prev_dis' title='" + _Language.Search.FindPrev + "' style='margin-left:4px; margin-top:4px' cmd='" + "SearchPrev" + "'></a>";
                }, 
                OnCommandStateChange: function (data) {
                    FXREADER.Common.UpdateBtnState('btnPrevSearch', "fwr_toolbar_search_prev_nor", "fwr_toolbar_search_prev_dis", data.state);
                }
            });
            _pReaderApp.AddCommand({
                state: false,
                name: "SearchPrev",
                exec: function (data) {
                    _SearchTextCall(0);
                }
            });
            _pReaderApp.AddCommandUI({
                UIName: "SearchNext",
                CommandName: 'SearchNext',
                State: false,
                CreateHtmlContentFunc: function () {
                    return "<a id='btnNextSearch' class='fwr_toolbar_btn fwr_toolbar_search_btn fwr_toolbar_search_next_dis' title='" + _Language.Search.FindNext + "' style='margin-right:4px; margin-top:4px' cmd='" + "SearchNext" + "'></a>";
                },
                OnCommandStateChange: function (data) {
                    FXREADER.Common.UpdateBtnState('btnNextSearch', "fwr_toolbar_search_next_nor", "fwr_toolbar_search_next_dis", data.state);
                }
            });
            _pReaderApp.AddCommand({
                state: false,
                name: "SearchNext",
                exec: function (data) {
                    _SearchTextCall(1);
                }
            });
        }

        //Doc View 消息响应;
        this.OnDocViewZoom = function (scale) {
            var pPageView = _pReaderApp.GetMainView().GetDocView().GetPageView(_nCurPageIndex);
            if (pPageView != null && _HighlightRects != null)
                _self.HighLightRects(pPageView, _HighlightRects);
        }



    }


    exports.Reader_CreatePlugin = function (pReaderApp) {
        var pFindToolPlugin = new FXREADER.CFindToolPlugin(pReaderApp);
        return pFindToolPlugin;
    }
});